package com.tjhk.netty.manager;


import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * ChannelManager
 */
public class ChannelManager {

    public static ChannelManager channelManager = new ChannelManager();
    private ChannelManager(){

    }

    public static ChannelManager instance(){
        return channelManager;
    }

    private static final Logger log = LoggerFactory.getLogger(ChannelManager.class);

    private static final AttributeKey<String> TERMINALS = AttributeKey.newInstance("terminalId");

    private ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    /** 保存 terminalId与ChannelId*/
    private Map<String, ChannelId> channelIdMap = new ConcurrentHashMap<>();

    private ChannelFutureListener remover = future -> {
        String terminalId = future.channel().attr(TERMINALS).get();
        if (channelIdMap.get(terminalId) == future.channel().id()) {
            channelIdMap.remove(terminalId);
        }
    };

    /**
     * @param terminalId
     * @param channel
     * @return
     */
    public boolean add(String terminalId, Channel channel) {
        if (terminalId == null){
            log.error("terminalId不为空！");
            return false;
        }
        boolean added = add(channel);
        if (added) {
            if (channelIdMap.containsKey(terminalId)) {//替换
                Channel old = get(terminalId);
                if (channel != old){
                    old.closeFuture().removeListener(remover);
                    old.close();
                }
            }
            channel.attr(TERMINALS).set(terminalId);
            channel.closeFuture().addListener(remover);
            channelIdMap.put(terminalId, channel.id());
        }
        return added;
    }

    /**
     * 加入Group
     * @param channel
     * @return
     */
    public boolean add(Channel channel) {
        if (channelGroup.contains(channel))
            return true;
        return channelGroup.add(channel);
    }

    /**
     * 从Group中删除
     * @param channel
     * @return
     */
    public boolean remove(Channel channel){
        deleteFromChannelIdMap(channel.id());
        return channelGroup.remove(channel.id());
    }

    public boolean remove(ChannelId id){
        deleteFromChannelIdMap(id);
        return channelGroup.remove(id);
    }

    private void deleteFromChannelIdMap(ChannelId id){
        if (channelIdMap.values().contains(id)){
            for (String k:channelIdMap.keySet()) {
                if (channelIdMap.get(k) == id)
                    channelIdMap.remove(k);
            }
        }
    }
    /**
     * 删除
     * @param terminalId
     * @return
     */
    public boolean remove(String terminalId) {
        ChannelId id = channelIdMap.remove(terminalId);
        if (id !=null)
            return remove(id);
        return true;
    }

    public Channel get(String terminalId) {
        ChannelId id = channelIdMap.get(terminalId);
        if (id !=null)
            return channelGroup.find(id);
        return null;
    }
    public String getTerminalId(Channel channel) {
        return channel.attr(TERMINALS).get();
    }
    public ChannelGroup getChannelGroup() {
        return channelGroup;
    }

    public boolean hasTerminal(String terminalId){
        if (channelIdMap.containsKey(terminalId)) {//替换
            Channel channel = get(terminalId);
            if (channel != null)
                return true;
        }
        return false;
    }
}